home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 May / macformat-024.iso / Shareware City / Developers / kvik / runtime libs / kviksl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-21  |  7.6 KB  |  393 lines  |  [TEXT/MPS ]

  1. /** kviksl.c
  2.  ** kvik standard library routines.
  3.  **
  4.  ** Written by and Copyright 1994 Asher Hoskins.
  5.  **
  6.  ** The author retains copyright on this implementation. Permission for
  7.  ** educational and non-profit use is granted to all. If you're planning to
  8.  ** make money with this or any code derived from it, check with the author
  9.  ** first.
  10.  **/
  11.  
  12. #include <stdio.h>
  13. #include "systypes.h"
  14. #include "systimeb.h"
  15. #include "timea.h"
  16. #include <ctype.h>
  17. #include <math.h>
  18. #include "kvikmath.h"
  19. #include "kvik_obj_types.h"
  20. #include "kvikrt.h"
  21. #include "kviksl.h"
  22.  
  23. #define PI 3.141592654
  24. #define MINUSZERO (0x8000)        /* any kviknum >= this is negative */
  25. #define LINEFEED (5000)            /* kviknum for 0,25 */
  26.  
  27. static kviknum hournum(void);
  28. static void writenum(kviknum, double, int);
  29. static double readnum(int *);
  30. static void add_character_to_packed(kviknum *, kviknum *, int);
  31. static void print_character_from_packed(kviknum *, kviknum, int);
  32. extern data_area_t *data;
  33.  
  34. int stdlib(int num, int r[], int p[], dp_t d[], int *gd)
  35. {
  36.     int ti, ti2;
  37.     double td;
  38.     kviknum tk;
  39.     FILE *outf;
  40.     data_area_t *data_p;
  41.  
  42.     switch (num) {
  43.  
  44.     case 11:
  45.         r[0] = doub2kvik(kvik2doub(r[0]) * kvik2doub(r[1]) * 20000.0);
  46.         break;
  47.  
  48.     case 12:
  49.         r[0] = doub2kvik(floor(kvik2doub(r[0]) / kvik2doub(r[1])) / 20000.0);
  50.         break;
  51.  
  52.     case 21:
  53.         r[0] = doub2kvik(kvik2doub(r[0]) / 400.0);
  54.         break;
  55.  
  56.     case 22:
  57.         r[0] = doub2kvik(kvik2doub(r[0])*400.0 - floor(kvik2doub(r[0])*400.0));
  58.         break;
  59.  
  60.     case 31:
  61.         r[0] = doub2kvik(kvik2doub(r[0]) * kvik2doub(r[1]) * 400.0);
  62.         break;
  63.  
  64.     case 32:
  65.         r[0] = doub2kvik((kvik2doub(r[0]) / kvik2doub(r[1])) / 400.0);
  66.         break;
  67.  
  68.     case 48:
  69.         r[0] = input_baudot();
  70.         break;
  71.     case 49:
  72.         break;
  73.  
  74.     case 100:
  75.         writenum(r[0], kvik2doub(r[0]), 5);
  76.         break;
  77.     case 101:
  78.         break;
  79.  
  80.     case 150:
  81.         r[0] = doub2kvik(readnum(&ti));
  82.         if (ti == EOF)
  83.             r[0] = OVERFLOW;
  84.         break;
  85.     case 151:
  86.         break;
  87.  
  88.     case 200:
  89.         printf("\r\n");
  90.         break;
  91.     case 201:
  92.         break;
  93.  
  94.     case 250:
  95.         /* This should really wait for CRLF, not just LF. */
  96.         while (getchar() != '\n')
  97.             ;
  98.         break;
  99.     case 251:
  100.         break;
  101.  
  102.     case 300:
  103.         writenum(r[0], kvik2doub(r[0])*20000.0, 0);
  104.         break;
  105.     case 301:
  106.         break;
  107.  
  108.     case 302:
  109.         writenum(r[0], kvik2doub(r[0])*400.0, 2);
  110.         break;
  111.     case 303:
  112.         break;
  113.  
  114.     case 350:
  115.         r[0] = doub2kvik(readnum(&ti)/20000.0);
  116.         if (ti == EOF)
  117.             r[0] = OVERFLOW;
  118.         break;
  119.     case 351:
  120.         break;
  121.  
  122.     case 352:
  123.         r[0] = doub2kvik(readnum(&ti)/400.0);
  124.         if (ti == EOF)
  125.             r[0] = OVERFLOW;
  126.         break;
  127.     case 353:
  128.         break;
  129.  
  130.     case 400:
  131.         td = kvik2doub(r[0]);
  132.         if (td >= 0.0)
  133.             r[0] = doub2kvik(sqrt(td));
  134.         else
  135.             r[0] = OVERFLOW;
  136.         break;
  137.  
  138.     case 450:
  139.         if (r[0] != OVERFLOW) {
  140.             td = kvik2doub(r[0]) * PI;
  141.             r[0] = doub2kvik(sin(td));
  142.         }
  143.         break;
  144.  
  145.     case 460:
  146.         if (r[0] != OVERFLOW) {
  147.             td = kvik2doub(r[0]) * PI;
  148.             r[0] = doub2kvik(cos(td));
  149.         }
  150.         break;
  151.  
  152.     case 470:
  153.         if (r[0] != OVERFLOW) {
  154.             td = kvik2doub(r[0]) * 400.0;
  155.             r[0] = doub2kvik(atan(td) / (PI/2));
  156.         }
  157.         break;
  158.  
  159.     case 480:
  160.         if (r[0] != OVERFLOW) {
  161.             td = kvik2doub(r[0]) + 1.0;
  162.             r[0] = doub2kvik(log2(td) / 400.0);
  163.         }
  164.         break;
  165.  
  166.     case 490:
  167.         if (r[0] != OVERFLOW) {
  168.             td = kvik2doub(r[0]);
  169.             r[0] = doub2kvik(pow(2, td) - 1);
  170.         }
  171.         break;
  172.  
  173.     case 530:
  174.         if (d[0].start != NULL) {
  175.             ti = d[0].offset;
  176.             tk = 0;
  177.             while (ti < d[0].size && tk != LINEFEED) {
  178.                 tk = input_baudot();
  179.                 if (tk >= MINUSZERO)
  180.                     tk = LINEFEED;
  181.                 d[0].start[ti] = tk;
  182.                 ti++;
  183.             }
  184.             if (ti == d[0].size)
  185.                 d[0].start[ti-1] = LINEFEED;
  186.         }
  187.         else {
  188.             puts("KVIK: TRIED TO READ LINE INTO UNINITIALISED STORAGE");
  189.             exit(1);
  190.         }
  191.         break;
  192.     case 531:
  193.         break;
  194.  
  195.     case 540:
  196.         if (d[0].start != NULL) {
  197.             ti = d[0].offset;
  198.             while (ti < d[0].size && d[0].start[ti] != LINEFEED) {
  199.                 output_baudot(d[0].start[ti]);
  200.                 ti++;
  201.             }
  202.             putchar('\n');
  203.         }
  204.         else {
  205.             puts("KVIK: TRIED TO WRITE LINE FROM UNINITIALISED STORAGE");
  206.             exit(1);
  207.         }
  208.         break;
  209.     case 541:
  210.         break;
  211.  
  212.     case 550:
  213.         if (d[0].start != NULL) {
  214.             ti = d[0].offset;
  215.             tk = 0;
  216.             while (ti < d[0].size && tk != LINEFEED) {
  217.                 d[0].start[ti] = 0;
  218.                 add_character_to_packed(&tk, &d[0].start[ti], 0);
  219.                 add_character_to_packed(&tk, &d[0].start[ti], 5);
  220.                 add_character_to_packed(&tk, &d[0].start[ti], 10);
  221.                 ti++;
  222.             }
  223.             if (ti == d[0].size)
  224.                 d[0].start[ti-1] = LINEFEED;
  225.         }
  226.         else {
  227.             puts("KVIK: TRIED TO READ LINE INTO UNINITIALISED STORAGE");
  228.             exit(1);
  229.         }
  230.         break;
  231.     case 551:
  232.         break;
  233.  
  234.     case 560:
  235.         if (d[0].start != NULL) {
  236.             ti = d[0].offset;
  237.             tk = 0;
  238.             while (ti < d[0].size && tk != LINEFEED) {
  239.                 print_character_from_packed(&tk, d[0].start[ti], 0);
  240.                 print_character_from_packed(&tk, d[0].start[ti], 5);
  241.                 print_character_from_packed(&tk, d[0].start[ti], 10);
  242.                 ti++;
  243.             }
  244.             putchar('\n');
  245.         }
  246.         else {
  247.             puts("KVIK: TRIED TO WRITE LINE FROM UNINITIALISED STORAGE");
  248.             exit(1);
  249.         }
  250.         break;
  251.     case 561:
  252.         break;
  253.  
  254.     case 666:
  255.         puts("KVIK: EMERGENCY STOP");
  256.         exit(1);
  257.  
  258.     case 888:
  259.         puts("KVIK: DUMPING STATE");
  260.         if ((outf = fopen("k.state.c", "w")) == NULL) {
  261.             puts("KVIK: CANNOT OPEN STATE FILE");
  262.             exit(1);
  263.         }
  264.         data_p = data;
  265.         while (data_p != NULL) {
  266.             fprintf(outf, "store = (kviknum *) alloc_storage(%d, %d, 0);\n",
  267.                 data_p->id, data_p->size);
  268.             for (ti2 = 0; ti2 < data_p->size; ti2++)
  269.                 fprintf(outf, "store[%d] = %d;\n", ti2, data_p->start[ti2]);
  270.             data_p = data_p->next;
  271.         }
  272.         for (ti = 0; ti < 10; ti++) {
  273.             fprintf(outf, "r[%d] = %d;\n", ti, r[ti]);
  274.             fprintf(outf, "p[%d] = %d;\n", ti, p[ti]);
  275.             if (d[ti].start != NULL)
  276.                 fprintf(outf, "set_dp_intoff(&d[%d], %d, %d);\n", ti, d[ti].id,
  277.                     d[ti].offset);
  278.         }
  279.         fclose(outf);
  280.         puts("KVIK: DUMPED STATE");
  281.         break;
  282.  
  283.     case 900:
  284.         r[0] = hournum();
  285.         break;
  286.  
  287.     default:
  288.         return(0);
  289.     }
  290.  
  291.     *gd = p[0];
  292.     return(1);
  293. }
  294.  
  295. /** Return the hour number / 24.0 in kviknum format.
  296.  **/
  297.  
  298. static kviknum hournum(void)
  299. {
  300.     time_t t;
  301.     struct tm *lt;
  302.  
  303.     t = time(NULL);
  304.     lt = localtime(&t);
  305.  
  306.     return(doub2kvik(lt->tm_hour / 24.0));
  307. }
  308.  
  309. /** Write a number to the screen, using ',' instead of a decimal point.
  310.  **/
  311.  
  312. static void writenum(kviknum k, double d, int prec)
  313. {
  314.     static char s[30];
  315.     int i;
  316.  
  317.     if (k == OVERFLOW) {
  318.         printf("OVERFLOW ");
  319.         return;
  320.     }
  321.  
  322.     sprintf(s, "%.*f ", prec, d);
  323.     if (prec > 0) {
  324.         for (i = 0; s[i] != '.'; i++)
  325.             ;
  326.         s[i] = ',';
  327.     }
  328.     printf(s);
  329. }
  330.  
  331. /** Read a number from the keyboard, using ',' instead of a decimal point.
  332.  **/
  333.  
  334. static double readnum(int *c)
  335. {
  336.     static char s[30];
  337.     int i;
  338.     double d;
  339.  
  340.     for (i=0; i<30 && isspace(s[i] = getchar()); i++)
  341.         ;
  342.     if (s[i] == ',')
  343.         s[i] = '.';
  344.     i++;
  345.     for (; i<30 && (isdigit(s[i] = *c = getchar()) || s[i] == ','); i++)
  346.         if (s[i] == ',')
  347.             s[i] = '.';
  348.  
  349.     if (i == 30 || *c == EOF)
  350.         return(0.0);        /* something probably went wrong */
  351.  
  352.     s[i] = '\0';
  353.     sscanf(s, "%lf", &d);
  354.  
  355.     return(d);
  356. }
  357.  
  358. /** Read a baudot character from the keyboard and add it to 'num', shifted
  359.  ** left by 'shift' places. The character read is returned in c. If the
  360.  ** function is entered with c set to LINEFEED it is assumed that the end
  361.  ** of the line has just been read and so the function exits without doing
  362.  ** anything.
  363.  **
  364.  ** NOTE: if the kviknum format changes then the 625 (= 20000/32) will
  365.  **       have to be changed.
  366.  **/
  367.  
  368. static void add_character_to_packed(kviknum *c, kviknum *num, int shift)
  369. {
  370.     if (*c == LINEFEED)
  371.         return;
  372.     *c = input_baudot();
  373.     if (*c >= MINUSZERO)
  374.         *c = LINEFEED;
  375.     *num |= (*c / 625) << shift;
  376. }
  377.  
  378. /** Write the baudot character stored in bits (shift):(shift+4) of num,
  379.  ** unless c is LINEFEED. Set c to the kviknum of the character printed.
  380.  **
  381.  ** NOTE: if the kviknum format changes then the 625 (= 20000/32) will
  382.  **       have to be changed.
  383.  **/
  384.  
  385. static void print_character_from_packed(kviknum *c, kviknum num, int shift)
  386. {
  387.     if (*c == LINEFEED)
  388.         return;
  389.     *c = ((num >> shift) & 0x1f) * 625;
  390.     output_baudot(*c);
  391. }
  392.  
  393.